第二章-神经网络基础(logistic 回归函数、向量化)

2.1 二分分类

  • 计算机保存一张图片,要保存三个独立矩阵,分别对应红、绿、蓝三个颜色通道 举例:图为一张猫图,像素为 64x64, 就有三个 64x64 的矩阵 course2-1.jpg
  • 用特征向量 x 来表示图片 则图片的维度n = nx = 64 * 64 * 3 = 12 288
  • 在二分类问题中,目标是训练出一个分类器(x 作为输入,预测输出的结果标签为 y) course2-2.jpg
  • 上图表现的是x是nx维的特征向量
  • 训练集由m个训练样本构成
  • X矩阵式m列 高为nx (训练样本作为列向量堆叠)(约定格式) 注: 也有(训练样本作为行向量堆叠)的矩阵形式,但在神经网络中一般用约定格式

2.2 logistic 回归模型

course2-3.jpg

course2-3.jpg

  • 线性回归中可用
  • y = w^t * x + b
  • 缺点: y 应该介于0和1之间
  • 可用sigmoid(z)函数,也就是上图中的G(z)
  • 对于参数 w 和 b :
  • b 对应一个拦截器

2.3 logistic 回归损失函数(成本函数)

  • 损失函数L(^y,y): 在单个训练样本中定义的,衡量了在单个训练样本上的表现
  • 成本函数(代价函数) J(w,b):衡量了在==全部训练样本==上的表现(在logistic函数中寻找合适的 w 和 b 让 y-hat 尽可能的小) course2-4.jpg

2.4 阶梯下降法

course2-5.jpg

course2-5.jpg

  • 成本函数 J (w,b)是一个凸函数(选择该函数的原因) 阶梯下降法的做法是: 从初始点开始,朝最陡的下坡方向走一步

2.5 向量化

  • 注:当你想写循环时,可以先检查numpy中是否有类似的内置函数
  • ==向量化速度比循环快300倍==(真是个神奇的东西)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    import time

    a = np.random.rand(1000000)
    b = np.random.rand(1000000)

    tic = time.time()
    c = np.dot(a,b)
    toc = time.time()

    print(c)
    print("Vectorized version(向量化):" + str(1000*(toc-tic))+"ms")

    c = 0
    tic = time.time()
    for i in range(1000000):
    c += a[i]*b[i]
    toc = time.time()

    print(c)
    print("For loop(循环):" + str(1000*(toc-tic))+ "ms")
1
2
3
4
5
# 输出
249961.060873
Vectorized version(向量化):2.0003318786621094ms
249961.060873
For loop(循环):779.0098190307617ms
  • np.dot(W,X): eg: 计算Z = W^T+ b,向量化可以直接计算w^T(表示W的转置)
    1
    Z = np.dot(W.T,X)+b

2.6 高度向量化的、非常高效的逻辑回归的梯度下降算法

course2-6.jpg

1
2
3
4
5
6
7
Z = wTX + b = np. dot(w. T, X)
A = σ(Z)
dZ = A -Y
dw = 1/m ∗ X ∗ dz^T
db = 1/m * np. sum(dZ)
w = w - α * dw
b = b - α * db

  • 我们利用前五个公式完成了前向和后向传播,也实现了对所有训练样本进行预测和求 导
  • 利用后两个公式,梯度下降更新参数。
  • 我们的目的是不使用for循环,所以我们就通过一次迭代实现一次梯度下降,但如果你希望多次迭代进行梯度下降,那么仍然需要for循环,放在最外层。不过我们还是觉得一次迭代就进行一次梯度下降,避免使用任何循环比较 舒服一些。

2.7 python中的广播机制( Broadcasting in Python)

1
2
3
4
5
import numpy as np
A = np.array([[56.0, 0.0, 4.4, 68.0],
[1.2, 104.0, 52.0, 8.0],
[1.8, 135.0, 99.0, 0.9]])
print(A)
1
2
3
[[  56.     0.     4.4   68. ]
[ 1.2 104. 52. 8. ]
[ 1.8 135. 99. 0.9]]
  • axis=0 意思是、在竖直方向上求和
  • axis=1 是在水平方向上求和
    1
    2
    cal = A.sum(axis=0)
    print(cal)
1
[  59.   239.   155.4   76.9]
1
2
percentage = 100*A/cal.reshape(1,4)
print(percentage)
1
2
3
[[ 94.91525424   0.           2.83140283  88.42652796]
[ 2.03389831 43.51464435 33.46203346 10.40312094]
[ 3.05084746 56.48535565 63.70656371 1.17035111]]
  1. axis 用来指明将要进行的运算是沿着 哪个轴执行,在 numpy 中, 0 轴是垂直的,也就是列,而 1 轴是水平的,也就是行
  2. A/cal.reshape(1,4)指令则调用了 numpy 中的广播机制
  • 这里使用3X4的矩阵 A 除以1X4 的矩阵 cal。技术上来讲,其实并不需要再将矩阵 cal reshape(重塑)成1X4 ,因 为矩阵 cal 本身已经是1X4 了。但是当我们写代码时不确定矩阵维度的时候,通常会对矩阵 进行重塑来确保得到我们想要的列向量或行向量。
  • 重塑操作 reshape是一个常量时间的操作, 时间复杂度是 O(1),它的调用代价极低。
  1. numpy 广播机制
  • 如果两个数组的后缘维度的轴长度相符或其中一方的轴长度为 1,则认为它们是广播兼容的。
  • 广播机制与执行的运算种类无关
  • 广播会在缺失维度和轴长度为 1 的维度上进行。 后缘维度的轴长度: A.shape[-1] 即矩阵维度元组中的最后一个位置的值 course2-7.jpg